Files for my website bwc9876.dev
at main 174 lines 3.9 kB view raw
1--- 2import { type CollectionEntry, getCollection, render } from "astro:content"; 3import { Image } from "astro:assets"; 4import Layout from "@layouts/Layout.astro"; 5import IconLink from "@components/IconLink.astro"; 6import { Icon } from "astro-icon/components"; 7export async function getStaticPaths() { 8 const renameEntries = await getCollection("projects"); 9 return renameEntries.map((entry) => ({ 10 params: { slug: entry.id }, 11 props: { entry } 12 })); 13} 14const { entry } = Astro.props as { entry: CollectionEntry<"projects"> }; 15const { Content } = await render(entry); 16 17const firstOtherLink = entry.data.links?.other?.[0]; 18 19const restOther = entry.data.links?.other?.slice(1); 20 21const og = { 22 src: entry.data.image, 23 alt: entry.data.name 24}; 25--- 26 27<Layout title={entry.data.name} description={entry.data.summary} keywords={entry.data.tags} og={og}> 28 <div class="hero"> 29 <div class="txt"> 30 <div class="project-header"> 31 <h1 class="gradient-text">{entry.data.name}</h1> 32 <p> 33 {entry.data.timespan.from}{entry.data.timespan.to && <> - {entry.data.timespan.to}</>}, 34 {entry.data.tags.join(", ")} 35 </p> 36 </div> 37 <p>{entry.data.summary}</p> 38 <div class="ctas"> 39 { 40 entry.data.links?.github && ( 41 <span> 42 <a href={`https://github.com/${entry.data.links.github}`} role="button"> 43 <Icon name="bi:github" /> GitHub 44 </a> 45 </span> 46 ) 47 } 48 { 49 firstOtherLink && ( 50 <span> 51 <a href={firstOtherLink.url} role="button" class="secondary"> 52 <Icon name={`${firstOtherLink.iconPackOverride ?? "bi"}:${firstOtherLink.icon}`} /> 53 {firstOtherLink.label} 54 </a> 55 </span> 56 ) 57 } 58 </div> 59 <div class="links"> 60 { 61 restOther && 62 restOther.map((l) => ( 63 <span> 64 <IconLink 65 icon={l.icon} 66 overridePack={l.iconPackOverride} 67 href={l.url} 68 placement="bottom" 69 label={l.label} 70 /> 71 </span> 72 )) 73 } 74 </div> 75 </div> 76 <div class="img-container"> 77 <Image 78 transition:name={`project-img-${entry.id}`} 79 alt={entry.data.name} 80 src={entry.data.image} 81 /> 82 </div> 83 </div> 84 <h2>About This Project</h2> 85 <Content /> 86</Layout> 87 88<style> 89 div.project-header h1 { 90 margin-bottom: var(--1); 91 } 92 93 div.project-header p { 94 font-size: var(--2); 95 margin: 0; 96 } 97 98 .hero { 99 display: flex; 100 gap: var(--5); 101 justify-content: space-between; 102 align-items: center; 103 margin: var(--4) 0; 104 } 105 106 @media (width <= 1300px) { 107 .hero { 108 flex-direction: column-reverse; 109 margin-top: var(--1); 110 gap: var(--2); 111 text-align: center; 112 } 113 114 .links, 115 .ctas { 116 margin: auto; 117 } 118 119 .hero p { 120 margin: 0; 121 } 122 123 div.project-header { 124 h1 { 125 margin-top: 0; 126 } 127 p { 128 text-wrap: balance; 129 } 130 } 131 } 132 133 .hero .txt { 134 width: 100%; 135 flex-grow: 1; 136 display: flex; 137 flex-direction: column; 138 gap: var(--2); 139 } 140 141 .hero .ctas { 142 display: flex; 143 align-items: center; 144 gap: var(--2); 145 } 146 147 .hero .ctas a[role="button"] { 148 display: flex; 149 align-items: center; 150 gap: var(--small); 151 } 152 153 .hero .img-container { 154 flex-grow: 1; 155 width: 100%; 156 justify-content: end; 157 align-items: center; 158 display: flex; 159 margin: auto; 160 } 161 162 .hero .img-container img { 163 border-radius: 5px; 164 filter: drop-shadow(0 0 100px color(from var(--primary) srgb r g b / 0.2)); 165 width: 60%; 166 height: auto; 167 margin: auto; 168 } 169 170 .links { 171 display: flex; 172 gap: var(--2); 173 } 174</style>